﻿using System.Text.Json;
using System.Text.Json.Nodes;
using VictoriaMetrics.Client;

namespace Test
{
    internal class Program
    {
        static async Task Main(string[] args)
        {
            //client must be singleton mode(必须是单例模式)
            var client = new VictoriaMetricsClient("http://127.0.0.1:8428");
            
            //import metrics
            var metrics = new MetricsEntity("m1");
            metrics.metric.Add("app", "qms");
            for (int i = 0; i < 10; i++)
            {
                metrics.values.Add(i);
                metrics.timestamps.Add(DateTimeOffset.Now.ToUnixTimeMilliseconds());
                Thread.Sleep(1);
            }
            await client.ImportMetricsAsync([metrics]);

            //import point data
            var pointList = new List<MetricsPointData>();
            for (int i = 0; i < 2; i++)
            {
                var point = new MetricsPointData("m1");
                point.Metric.Add("app", "qms");
                point.Time = DateTimeOffset.Now;
                point.Value = Random.Shared.NextDouble();
                pointList.Add(point);

                Thread.Sleep(1);
            }
            await client.ImportPointAsync(pointList);

            //import list
            var list = new List<People>();
            for (int i = 0; i < 10; i++)
            {
                var p = new People
                {
                    Time = DateTimeOffset.Now,
                    app = "qms",
                    v1 = i,
                    v2 = Random.Shared.Next(1000, 9999)
                };
                await Task.Delay(1);
                list.Add(p);
            }
            await client.ImportEntityAsync("m1", list);

            //import by your self
            await client.ImportAsync(async stream =>
            {
                var writer = new MetricsWriter(stream);

                var metrics = new MetricsEntity("m1");
                metrics.metric.Add("app", "qms");
                metrics.values.Add(1);
                metrics.timestamps.Add(DateTimeOffset.Now.ToUnixTimeMilliseconds());
                await writer.WriteMetricsAsync(metrics);

                await writer.WriteNAsync(); //write an \n
                Thread.Sleep(1);

                var point = new MetricsPointData("m1");
                point.Metric.Add("app", "qms");
                point.Time = DateTimeOffset.Now;
                point.Value = Random.Shared.NextDouble();
                pointList.Add(point);
                await writer.WritePointAsync(point);

                await writer.WriteNAsync(); //write an \n
                Thread.Sleep(1);

                var p = new People
                {
                    Time = DateTimeOffset.Now,
                    app = "qms",
                    v1 = 12,
                    v2 = Random.Shared.Next(1000, 9999)
                };

                await writer.WriteEntityAsync("m1", p);
            });

            //export jsonline
            var jsonlineData = client.ExportJsonline(null, DateTimeOffset.Now.AddMinutes(-30), DateTimeOffset.Now, true);
            await foreach (var item in jsonlineData)
            {
                Console.WriteLine(item);
            }

            Console.WriteLine("=========================");

            //export metrics
            var metricsData = client.ExportMetrics(null, DateTimeOffset.Now.AddMinutes(-30), DateTimeOffset.Now, true);
            await foreach (var item in metricsData)
            {
                Console.WriteLine($"{item.metric["__name__"]}==>{item.metric["app"]}==>{item.timestamps.Count}==>{item.values.Count}");
            }

            Console.WriteLine("=========================");

            //export point
            var pointData = client.ExportPoint(null, DateTimeOffset.Now.AddMinutes(-30), DateTimeOffset.Now, true);
            await foreach (var item in pointData)
            {
                Console.WriteLine($"{item.MetricName}==>{item.Metric["app"]}==>{item.Time}==>{item.Value}");
            }

            Console.WriteLine("=========================");

            //export list
            var listData = await client.ExportListAsync<People>(null, DateTimeOffset.Now.AddMinutes(-30), DateTimeOffset.Now);
            Console.WriteLine(JsonSerializer.Serialize(listData));

            Console.WriteLine("=========================");

            var query1 = """
                m1{app="qms"}
                """;

            //query stream
            using var stream = await client.QueryStreamAsync(query1, DateTimeOffset.Now.AddMinutes(-30), DateTimeOffset.Now);
            using var sr = new StreamReader(stream);
            Console.WriteLine(sr.ReadToEnd());

            Console.WriteLine("=========================");

            //query range
            var data1 = await client.QueryAsync<JsonObject>(query1, DateTimeOffset.Now.AddMinutes(-30), DateTimeOffset.Now);
            Console.WriteLine(JsonSerializer.Serialize(data1));

            Console.WriteLine("=========================");

            //query result
            var data2 = await client.QueryResultAsync(query1, DateTimeOffset.Now.AddMinutes(-30), DateTimeOffset.Now);
            Console.WriteLine(JsonSerializer.Serialize(data2));

            //queue
            var queue = new VictoriaMetricsQueue(client);
            _ = Task.Run(async () =>
            {
                while (true)
                {
                    //metrics
                    var metrics = new MetricsEntity("m1");
                    metrics.metric.Add("app", "qms");
                    metrics.values.Add(Random.Shared.Next(1, 1000));
                    metrics.timestamps.Add(DateTimeOffset.Now.ToUnixTimeMilliseconds());
                    queue.Add(metrics);
                    await Task.Delay(1);

                    //point
                    var point = new MetricsPointData("m1");
                    point.Metric.Add("app", "qms");
                    point.Value = Random.Shared.Next(1, 1000);
                    point.Time = DateTimeOffset.Now;
                    queue.Add(point);
                    await Task.Delay(1);

                    //entity
                    var p = new People
                    {
                        Time = DateTimeOffset.Now,
                        app = "qms",
                        v1 = Random.Shared.Next(1, 1000),
                        v2 = Random.Shared.Next(1000, 9999)
                    };
                    queue.Add(p, "m1");

                    await Task.Delay(10);
                }

            });

            Console.WriteLine("Hello, World!");
            Console.ReadKey();
        }
    }
}
